﻿using AutoMapper;
using Newtonsoft.Json;
using XXS.Common.Paginate;

namespace XXS.Common.BaseDomain
{
    public abstract class BaseDomain
    {
        protected BaseDomain()
        {
            InitMapper();
        }

        /// <summary>
        ///     映射引擎
        /// </summary>
        protected IMapper Im;

        [JsonIgnore]
        public IConfigurationProvider ConfigurationProvider => Im?.ConfigurationProvider;

        /// <summary>
        ///     引擎配置
        /// </summary>
        protected abstract IMapper InitMapper();
    }

    /// <summary>
    /// 是 T1 数据映射到 T2 中,意图为将数据从别的类映射到自己.
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <typeparam name="T2"></typeparam>
    public class MapFromBaseDomain<T1, T2> : BaseDomain, IMapFrom<T1, T2>, IMapFrom<T2> where T2 : class, new()
    {
        /// <summary>
        ///     数据映射
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public virtual T2 MapFrom(T1 source)
        {
            return Im.Map(source, new T2());
        }

        /// <summary>
        ///     基础键值对Mapper
        /// </summary>
        protected override IMapper InitMapper()
        {
            return Im = new MapperConfiguration(mc => { mc.CreateMap<T1, T2>(); }).CreateMapper();
        }

        public T2 MapFrom(object source)
        {
            return Im.Map(source, new T2());
        }
    }

    /// <summary>
    /// 是 T1 数据映射到 T2 中,意图为将数据从自己输出到别的类
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <typeparam name="T2"></typeparam>
    public class MapToBaseDomain<T1, T2> : BaseDomain, IMapTo<T2> where T2 : class, new()
    {
        public virtual T2 MapTo(T2 destination)
        {
            return Im.Map(this, destination ?? new T2());
        }

        public virtual T2 MapTo<T2>() where T2 : new()
        {
            return Im.Map(this, new T2());
        }

        /// <summary>
        ///     基础键值对Mapper
        /// </summary>
        protected override IMapper InitMapper()
        {
            return Im = new MapperConfiguration(mc => { mc.CreateMap<T1, T2>(); }).CreateMapper();
        }
    }

    /// <summary>
    /// 数据双向映射
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <typeparam name="T2"></typeparam>
    public class DoubleMapBaseDomain<T1, T2> : MapFromBaseDomain<T1, T2>, IMapTo<T1> where T2 : class, new() where T1 : class, new()
    {
        public T1 MapTo(T1 destination)
        {
            return Im.Map(this, destination ?? new T1());
        }

        public T2 MapTo(T2 destination)
        {
            return Im.Map(this, destination ?? new T2());
        }

        /// <summary>
        ///     基础键值对Mapper
        /// </summary>
        protected override IMapper InitMapper()
        {
            return Im = new MapperConfiguration(mc =>
            {
                mc.CreateMap<T1, T2>();
                mc.CreateMap<T2, T1>();
            }).CreateMapper();
        }
    }
}
